package com.navinfo.opentsp.platform.computing.serializer;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Charsets;
import com.navinfo.opentsp.platform.computing.util.DateUtils;
import com.navinfo.opentsp.platform.location.protocol.common.LCTireTemperatureDFAddition;
import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.serialization.EventSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * tirePressureDFAdditionData信息
 * HDFS_Sink的tirePressureDFAdditionData序列化器，拼接成字段间通过\001分割的字符串
 */
public class HDFSTirePressureDFAdditionDataSerializer implements EventSerializer {
    private static final Logger logger = LoggerFactory.getLogger(HDFSTirePressureDFAdditionDataSerializer.class);

    private final String APPEND_NEWLINE = "appendNewline";
    private final boolean appendNewline;
    private final String splitStr = "\001";
    private final OutputStream out;

    private HDFSTirePressureDFAdditionDataSerializer(OutputStream out, Context ctx) {
        this.appendNewline = ctx.getBoolean(APPEND_NEWLINE, true);
        this.out = out;
    }

    @Override
    public boolean supportsReopen() {
        return false;
    }
    @Override
    public void afterCreate() {}
    @Override
    public void afterReopen() {}
    @Override
    public void beforeClose() {}
    @Override
    public void flush() throws IOException {
        this.out.flush();
    }
    @Override
    public void write(Event event) throws IOException {
        try {
            //拼写落盘到HDFS的字符串。字段间分隔符是\001，null通过\N表示
            LCTireTemperatureDFAddition.TireTemperatureDFAddition tirePressureDFAdditionData = LCTireTemperatureDFAddition.TireTemperatureDFAddition.parseFrom(event.getBody());
            StringBuilder tirePressureDFAdditionDataStr = new StringBuilder(5000);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getVehType()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getTyreCount()).append(splitStr);
            tirePressureDFAdditionDataStr.append(JSON.toJSON(getTireConditionItemDtos(tirePressureDFAdditionData.getTireConditionItemList()))).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getAlarmSign()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getStatus()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getLatitude()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getLongitude()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getHeight()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getDirection()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getGpsTime()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getGpsSpeed()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getTerminalId()).append(splitStr);
            tirePressureDFAdditionDataStr.append(tirePressureDFAdditionData.getSerialNumber()).append(splitStr);

            //添加字段只能在分割线之上添加,注意时间分区这块，终端传的时候是秒还是毫秒
            //------------------------------------------分割线----------------------------------------
            tirePressureDFAdditionDataStr.append(DateUtils.format(tirePressureDFAdditionData.getGpsTime() * 1000, "yyyyMMdd"));
            //将数据拼接后写入hdfs
            this.out.write(tirePressureDFAdditionDataStr.toString().getBytes(Charsets.UTF_8));
            if (this.appendNewline) {
                this.out.write(10);
            }
        }catch (Exception e){
            logger.error("执行HDFS的HDFSTirePressureDFAdditionDataSerializer拦截器失败：" + e.getMessage(), e);
        }
    }

    public static List<TireConditionDto> getTireConditionItemDtos(List<LCTireTemperatureDFAddition.TireConditionItem> items){
        List<TireConditionDto> itemDtos = new ArrayList<>();
        if(items == null){
            return itemDtos;
        }
        for(LCTireTemperatureDFAddition.TireConditionItem item : items){
            TireConditionDto tireConditionDto = new TireConditionDto();
            tireConditionDto.setTyreHorizontalPosition(item.getTyreHorizontalPosition());
            tireConditionDto.setTyreVerticalPosition(item.getTyreVerticalPosition());
            tireConditionDto.setBatteryStatus(item.getBatteryStatus());
            tireConditionDto.setUnBalance(item.getUnBalance());
            tireConditionDto.setAirLeakage(item.getAirLeakage());
            tireConditionDto.setHighTemperature(item.getHighTemperature());
            tireConditionDto.setNoRFSignal(item.getNoRFSignal());
            tireConditionDto.setNoMatch(item.getNoMatch());
            tireConditionDto.setTirePressureAlarm(item.getTirePressureAlarm());
            tireConditionDto.setTyrePressure(item.getTyrePressure());
            tireConditionDto.setTyreTemperature(item.getTyreTemperature());
            tireConditionDto.setTemAlarmThreshold(item.getTemAlarmThreshold());
            tireConditionDto.setTyreHalarmThreshold(item.getTyreHalarmThreshold());
            tireConditionDto.setTyreLalarmThreshold(item.getTyreLalarmThreshold());
            tireConditionDto.setTyreNomimalValue(item.getTyreNomimalValue());
            tireConditionDto.setTireLocation(item.getTireLocation());
            tireConditionDto.setTyrePressureStatus( item.getTyrePressureStatus());
            tireConditionDto.setTyreBurstStatus(item.getTyreBurstStatus());
            tireConditionDto.setTyreOverTemperatureStatus(item.getTyreOverTemperatureStatus());
            tireConditionDto.setTyreLockDetectionStatus(item.getTyreLockDetectionStatus());
            tireConditionDto.setTfaStatus(item.getTfaStatus());
            tireConditionDto.setPlaceholder1(item.getPlaceholder1());
            tireConditionDto.setPlaceholder2(item.getPlaceholder2());
            itemDtos.add(tireConditionDto);
        }
        return itemDtos;
    }

    public static class Builder implements EventSerializer.Builder {
        public Builder() { }
        @Override
        public EventSerializer build(Context context, OutputStream out) {
            return  new HDFSTirePressureDFAdditionDataSerializer(out, context);
        }
    }

    static class TireConditionDto{
        int tyreHorizontalPosition;
        int tyreVerticalPosition;
        int batteryStatus;
        int unBalance;
        int airLeakage;
        int highTemperature;
        int noRFSignal;
        int noMatch;
        int tirePressureAlarm;
        int tyrePressure;
        int tyreTemperature;
        int temAlarmThreshold;
        int tyreHalarmThreshold;
        int tyreLalarmThreshold;
        int tyreNomimalValue;
        int tireLocation;
        int tyrePressureStatus;
        int tyreBurstStatus;
        int tyreOverTemperatureStatus;
        int tyreLockDetectionStatus;
        int tfaStatus;
        int placeholder1;
        int placeholder2;

        public int getTyreHorizontalPosition() {
            return tyreHorizontalPosition;
        }

        public void setTyreHorizontalPosition(int tyreHorizontalPosition) {
            this.tyreHorizontalPosition = tyreHorizontalPosition;
        }

        public int getTyreVerticalPosition() {
            return tyreVerticalPosition;
        }

        public void setTyreVerticalPosition(int tyreVerticalPosition) {
            this.tyreVerticalPosition = tyreVerticalPosition;
        }

        public int getBatteryStatus() {
            return batteryStatus;
        }

        public void setBatteryStatus(int batteryStatus) {
            this.batteryStatus = batteryStatus;
        }

        public int getUnBalance() {
            return unBalance;
        }

        public void setUnBalance(int unBalance) {
            this.unBalance = unBalance;
        }

        public int getAirLeakage() {
            return airLeakage;
        }

        public void setAirLeakage(int airLeakage) {
            this.airLeakage = airLeakage;
        }

        public int getHighTemperature() {
            return highTemperature;
        }

        public void setHighTemperature(int highTemperature) {
            this.highTemperature = highTemperature;
        }

        public int getNoRFSignal() {
            return noRFSignal;
        }

        public void setNoRFSignal(int noRFSignal) {
            this.noRFSignal = noRFSignal;
        }

        public int getNoMatch() {
            return noMatch;
        }

        public void setNoMatch(int noMatch) {
            this.noMatch = noMatch;
        }

        public int getTirePressureAlarm() {
            return tirePressureAlarm;
        }

        public void setTirePressureAlarm(int tirePressureAlarm) {
            this.tirePressureAlarm = tirePressureAlarm;
        }

        public int getTyrePressure() {
            return tyrePressure;
        }

        public void setTyrePressure(int tyrePressure) {
            this.tyrePressure = tyrePressure;
        }

        public int getTyreTemperature() {
            return tyreTemperature;
        }

        public void setTyreTemperature(int tyreTemperature) {
            this.tyreTemperature = tyreTemperature;
        }

        public int getTemAlarmThreshold() {
            return temAlarmThreshold;
        }

        public void setTemAlarmThreshold(int temAlarmThreshold) {
            this.temAlarmThreshold = temAlarmThreshold;
        }

        public int getTyreHalarmThreshold() {
            return tyreHalarmThreshold;
        }

        public void setTyreHalarmThreshold(int tyreHalarmThreshold) {
            this.tyreHalarmThreshold = tyreHalarmThreshold;
        }

        public int getTyreLalarmThreshold() {
            return tyreLalarmThreshold;
        }

        public void setTyreLalarmThreshold(int tyreLalarmThreshold) {
            this.tyreLalarmThreshold = tyreLalarmThreshold;
        }

        public int getTyreNomimalValue() {
            return tyreNomimalValue;
        }

        public void setTyreNomimalValue(int tyreNomimalValue) {
            this.tyreNomimalValue = tyreNomimalValue;
        }

        public int getTireLocation() {
            return tireLocation;
        }

        public void setTireLocation(int tireLocation) {
            this.tireLocation = tireLocation;
        }

        public int getTyrePressureStatus() {
            return tyrePressureStatus;
        }

        public void setTyrePressureStatus(int tyrePressureStatus) {
            this.tyrePressureStatus = tyrePressureStatus;
        }

        public int getTyreBurstStatus() {
            return tyreBurstStatus;
        }

        public void setTyreBurstStatus(int tyreBurstStatus) {
            this.tyreBurstStatus = tyreBurstStatus;
        }

        public int getTyreOverTemperatureStatus() {
            return tyreOverTemperatureStatus;
        }

        public void setTyreOverTemperatureStatus(int tyreOverTemperatureStatus) {
            this.tyreOverTemperatureStatus = tyreOverTemperatureStatus;
        }

        public int getTyreLockDetectionStatus() {
            return tyreLockDetectionStatus;
        }

        public void setTyreLockDetectionStatus(int tyreLockDetectionStatus) {
            this.tyreLockDetectionStatus = tyreLockDetectionStatus;
        }

        public int getTfaStatus() {
            return tfaStatus;
        }

        public void setTfaStatus(int tfaStatus) {
            this.tfaStatus = tfaStatus;
        }

        public int getPlaceholder1() {
            return placeholder1;
        }

        public void setPlaceholder1(int placeholder1) {
            this.placeholder1 = placeholder1;
        }

        public int getPlaceholder2() {
            return placeholder2;
        }

        public void setPlaceholder2(int placeholder2) {
            this.placeholder2 = placeholder2;
        }
    }
}
